﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;

namespace PasswordProvider.ObjectModel 
{    
    [DataContract]
    public abstract class DataObject : INotifyPropertyChanged
    {
        public static void Commit()
        {
            FileHelper.Save(PasswordProviderData.Current);
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises this object's PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The property that has a new value.</param>
        internal protected virtual void OnPropertyChanged(string propertyName)
        {
            this.VerifyPropertyName(propertyName);

            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }

        /// <summary>
        /// Generic method to set a property value with equality 
        /// checking and raising the property changed event. Returns false when value == field
        /// </summary>
        internal protected bool SetPropertyValue<T>(T value, ref T field, string propertyName)
        {
            if ((value != null && !value.Equals(field)) || (value == null && field != null))
            {
                field = value;
                OnPropertyChanged(propertyName);
                return true;
            }
            return false;
        }

        #endregion

        #region Private Helpers

        /// <summary>
        /// Warns the developer if this object does not have
        /// a public property with the specified name. This 
        /// method does not exist in a Release build.
        /// </summary>
        [Conditional("DEBUG")]
        [DebuggerStepThrough]
        private void VerifyPropertyName(string propertyName)
        {            
            // Verify that the property name matches a real,  
            // public OR non-public, instance property on this object.
            var prop = from p in this.GetType().GetProperties(System.Reflection.BindingFlags.NonPublic)
                       where p.Name == propertyName
                       select p;
            
            if(prop == null)
                Debug.Fail ("Invalid property name: " + propertyName);

        }

        #endregion
    }
}
